home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / win_utl1 / giveup2.zip / GIVE-UP.ASM next >
Assembly Source File  |  1996-03-23  |  33KB  |  410 lines

  1. ; This program calls Int 2F, function 1680h, to give OS/2, Desqview, etc.
  2. ;   a chance to use wasted CPU cycles.
  3. ;
  4. ; The program also hooks the DOS multiplex interrupt, Int 2Fh, for an installation check.
  5. ;
  6. ; 08 Nov. 1995 -- 1st release -- Gives up just a little too much.  Needs major work!!
  7. ;
  8. ; 09 Nov. 1995 -- 2nd release -- Fixed screwup in TSR paragraph calculation.  Does not
  9. ;                                  noticeably return CPU cycles, but no more bizarro
  10. ;                                  lockups and segment faults.
  11. ;
  12. ; 10 Nov. 1995 -- 3rd release -- Modified code to use Int 2F, Function 1680h, Release
  13. ;                                  current virtual machine time slice, instead of just 
  14. ;                                  calling the DOS idle interrupt.  Found this in PC
  15. ;                                  Interrupts, 2nd edition.  Works well, but needs some
  16. ;                                  tuning parameters added.  Giving up slices 18 times
  17. ;                                  a second is a bit much.
  18. ;
  19. ; 11 Nov. 1995 -- 4th release -- Began adding tuning parameters.  Fixed a bug in the int 1C
  20. ;                                  ISR.  The IRET in the old int 2F handler was popping AX
  21. ;                                  instead of the flags.  Rearranged the push ax and the pushf
  22. ;                                  to fix it.
  23. ;
  24. ; 23 Nov. 1995 -- 5th release -- Added elapsed tick counter, and logic to increment it on every 
  25. ;                                  timer tick, to the int 1C isr.  In order to make this work, I
  26. ;                                  had to use the CS segment override on the inc instruction.  I
  27. ;                                  intend to use this to trigger the call to int 2F, function 1680h
  28. ;                                  after so many ticks as opposed to every one.
  29. ;                             -- Added whenmask to hold a value for controlling when to release a 
  30. ;                                  CPU cycle.  Essentially I AND elapsed with whenmask, and if the 
  31. ;                                  is not zero then it's time to release a CPU cycle.  Currently
  32. ;                                  whenmask is set at 4, so int 2F, function 1680h is getting 
  33. ;                                  called every 4 ticks instead of every tick.
  34. ;
  35. ; 24 Nov. 1995 -- 6th release -- Corrected bug with the trigger logic.  Logical AND is not the
  36. ;                                  proper way to do this, because it does not cause the event
  37. ;                                  to happen every whenmask ticks.  Changed it to use straight
  38. ;                                  comparison, and elapsed to reflect ticks since last event.
  39. ;                                  It is much smoother now.
  40. ;                             -- Added code in the installation portion of the program to find
  41. ;                                  the trigger interval on the command line passed as /XX where
  42. ;                                  for the present both digits must be passed.  XX can range from
  43. ;                                  0 to 99.  If nothing is passed, the default is every 4 ticks.
  44. ;
  45. ; 24 Nov. 1995 -- 7th release -- Changed the ownership message to reflect the Bionic Fish 
  46. ;                                  Software Foundry.  This is preparatory to releasing as freeware.
  47. ;                                  Freeware release will occur 24 Nov. 1995 via upload to EXEC-PC.
  48. ;
  49. ; 20 Feb. 1996 -- 8th release -- Began working on V1R8.  Will not allow Disk I/O or Mouse operations 
  50. ;                                  to be interrupted.  This will be accomplished by creating a 
  51. ;                                  semaphore variable, and using it control whether the interruption
  52. ;                                  occurs when it is supposed to.  Instead, it will reset the counter
  53. ;                                  to zero, and IRET.  The mouse will be done first, and I am going
  54. ;                                  to assume the mouse is MS compatible, and has an Int 33h API.
  55. ;                             -- Code for the mouse exclusion is in place.  Sema is the semaphore
  56. ;                                  variable.  0 = activation allowed, >0 = activation NOT allowed.
  57. ;                                  Because I will also use this semaphore for the Disk I/O, I must
  58. ;                                  accept that the semaphore may be greater than 1, because a disk
  59. ;                                  event may be interrupted by a mouse event and vice versa.
  60. ;                             -- Code for trapping int 33h, mouse api, is in place.  A simple wrapper,
  61. ;                                  it should cause extremely minimal performance degradation.                                  
  62. ;                             -- Because of the code required for hooking the mouse interrupt, the
  63. ;                                  conditional jmp at the end of the install_chek had to be modified.
  64. ;                                  The conditional jump now checks if installation has not occured, and
  65. ;                                  bypasses the unconditional jmp if it has NOT.
  66. ;                             -- Code for Disk I/O trapping, BIOS int 13h, is in place.  Same concept
  67. ;                                  as the mouse trap.
  68. ;                             -- With both of these changes in place, performance in a full screen DOS
  69. ;                                  session under OS/2 Warp with the interval set at 6 ticks, AutoSketch
  70. ;                                  runs noticeably better than it did, but not better enough.  More work
  71. ;                                  must be done to improve overall system performance.  However, I am 
  72. ;                                  putting it into production on my system today.
  73. ;
  74. ; 08 Mar. 1996 -- 9th release -- Added code to retrieve the address of the In-DOS flag during the install
  75. ;                                  phase.  The address is stored in the indos_flg variable.  I have not 
  76. ;                                  decided how to use the In-DOS flag, however.
  77. ;                             -- Added code to retrieve the address of the DOS Critical Error flag.  The
  78. ;                                  address is stored in the crter_flg variable.  As with the In-DOS flag,
  79. ;                                  I haven't decided how to use it.
  80. ;                             -- Changed the jne conditional jump in the elapsed to whenmask comparison
  81. ;                                  to a jb jump.  This will guarantee that the release will happen and
  82. ;                                  get resynchronized if elapsed should happen to become greater than
  83. ;                                  whenmask.
  84. ;                             -- Added code to the Int 1C isr to check the In-DOS flag and prevent 
  85. ;                                  activation if set.
  86. ;                             -- Added code to the Int 1C isr to check the Critical Error flag and 
  87. ;                                  prevent activation if set.
  88. ;                             -- Removed Hard Disk BIOS & Mouse Semaphores.  The Critical Error and
  89. ;                                  In-DOS flag checks do much better.
  90. ;                             -- Added code to hook the DOS Idle Interrupt, Int 28h.  Since the In-DOS
  91. ;                                  flag is set during an Int 28h call, it is necessary to hook this in
  92. ;                                  order for cycles to be released during input wait loops.  Unlike the
  93. ;                                  Int 1Ch isr, the Int 28h service routine releases cycles every time
  94. ;                                  it is invoked.
  95. ;                             -- Works great!!  The only hitch is a slower ramp up to maximum file xfer
  96. ;                                  speed in Telix for Windows.  However, the fact that Windows runs under
  97. ;                                  OS/2 Warp with give-up being loaded in the OS/2 autoexec.bat speaks
  98. ;                                  major things about this release.  It goes into production in my OS/2
  99. ;                                  autoexec.bat today.  This means every WIN-OS/2 session will have give-up
  100. ;                                  running in the background.
  101. ;
  102. ; 09 Mar. 1996 --10th release -- The final modification before releasing this as a new version is a change
  103. ;                                  to the loader.  Instead of executing and then going TSR, I think it 
  104. ;                                  allocate a block of DOS memory as high in MCB chain as possible, copy
  105. ;                                  only the ISRs and their data into it, changing the allocated MCB's 
  106. ;                                  owner to 0x08h, MS-DOS, linking the ISRs into the IVT chains, and then
  107. ;                                  exiting normally.  By allocating the memory from the top, a hole will 
  108. ;                                  not be left when the loader portion terminates.  In order for this to work,
  109. ;                                  it is necessary to reallocate the MCB used by give-up itself.
  110. ;                             -- Added code to reallocate the Give-up MCB to only the actual amount used.
  111. ;                             -- Added code to allocate a block of memory and then change its owner to DOS.
  112. ;                                  This block of memory will not get released when the program terminates.
  113. ;                             -- Added code to calculate the new ISR offsets.  When the code is moved into
  114. ;                                  the new segment, the offsets will be true offsets from the beginning of
  115. ;                                  the segment, as opposed to the beginning of a .COM program where the PSP
  116. ;                                  must be accounted for.
  117. ;                             -- Added code to copy the ISR code and data to its new location in memory.
  118. ;                             -- Removed TSR memory calculation and TSR exit code.  Also changed the exit
  119. ;                                  label from not_tsr_exit to plain exit.
  120. ;                             -- Because all of the original offsets and addresses are calculated with an
  121. ;                                  ORG of 256 because this starts as a .COM program, I had to adjust all of
  122. ;                                  the offsets in variable and address references in the ISR routines.  
  123. ;                                  These are the -256 additions throughout this sections of the code.
  124. ;                             -- Works!! memory footprint is a mere 160 bytes!!  Going into production use.
  125. ;
  126. ; 23 Mar. 1996 --11th release -- Officially changing the version from v1r10 to v2r1, and corrected the startup
  127. ;                                  message to reflect this.  Will release to Exec-pc on Sunday, 24 Mar. 1996.
  128.  
  129. _CODE SEGMENT
  130. ASSUME CS:_CODE, DS:_CODE, ES:_CODE
  131. ORG 100h
  132.  
  133. start:
  134.   jmp install                                                        ; Jump to the installation code
  135.  
  136.   oldint1c  dd  00000000h                                            ; Old int 1Ch, timer, ivt entry
  137.   oldint28  dd  00000000h                                            ; Old int 28h, DOS Idle, ivt entry
  138.   oldint2f  dd  00000000h                                            ; Old int 2Fh, multiplex, ivt entry
  139.  
  140.   indos_flg dd  00000000h                                            ; Address of In-DOS flag
  141.   crter_flg dd  00000000h                                            ; Address of Critical Error Flag
  142.  
  143.   elapsed   dw  0000h                                                ; Ticks elapsed since program load
  144.   whenmask  dw  0004h                                                ; When to activate
  145.  
  146. int28_isr:                                                           ; Interrupt 28h, ISR
  147.   pushf                                                              ; Push flags onto stack
  148.   call cs:oldint28-256                                               ; Transfer control to old interrupt handler
  149.   push ax                                                            ; Preserve AX
  150.   mov ax,1680h                                                       ; Int 2F, function 1680h, Release current time slice
  151.   pushf                                                              ; Push flags onto stack
  152.   call cs:oldint2f-256                                               ; Call multiplex interrupt
  153.   pop ax                                                             ; Restore AX
  154.   iret                                                               ; Interrupt return 
  155.  
  156. int2f_isr:                                                           ; Interrupt 2Fh ISR
  157.   cmp ax,0BADDh                                                      ; 0xBADD is my multiplex ID
  158.   je int2f_isr_srvc                                                  ; If AX=0xBADDh then service the request
  159.   jmp cs:oldint2f-256                                                ; Transfer control to old int 2Fh ISR otherwise
  160. int2f_isr_srvc:                                                      ; Custom int 2Fh code is here
  161.   mov ax,0FADEh                                                      ; AX=0xFADEh, then GIVE-UP is installed
  162.   iret                                                               ; Interrupt return
  163.  
  164. int1c_isr:                                                           ; Interrupt 1Ch ISR
  165.   pushf                                                              ; Push flags onto stack
  166.   call cs:oldint1c-256                                               ; Transfer control to the old interrupt handler
  167.   push bx                                                            ; Preserve BX
  168.   mov bx,word ptr cs:[elapsed-256]                                   ; Copy to temporary storage
  169.   cmp bx,word ptr cs:[whenmask-256]                                  ; Is it time to trigger                   
  170.   pop bx                                                             ; Restore BX
  171.   jb int1c_isr_inc                                                   ; If less than then increment elapsed and return
  172.   push ax                                                            ; Preserve AX
  173.   push bx                                                            ; Preserve BX
  174.   push es                                                            ; Preserve ES
  175.   mov ax,0001h                                                       ; Set AX to 1
  176.   mov bx,word ptr cs:[indos_flg+2-256]                               ; Point ES to In-DOS flag
  177.   mov es,bx
  178.   mov bx,word ptr cs:[indos_flg-256]                                 ; Point BX to In-DOS flag
  179.   cmp al,byte ptr es:[bx]                                            ; See if In-DOS flag is set
  180.   pop es                                                             ; Restore ES
  181.   pop bx                                                             ; Restore BX
  182.   pop ax                                                             ; Restore AX
  183.   jae int1c_isr_reset                                                ; If In-DOS is set reset elapsed and return
  184.   push ax                                                            ; Preserve AX
  185.   push bx                                                            ; Preserve BX
  186.   push es                                                            ; Preserve ES
  187.   mov ax,0001h                                                       ; Set AX to 1
  188.   mov bx,word ptr cs:[crter_flg+2-256]                               ; Point ES to Critical Error flag
  189.   mov es,bx
  190.   mov bx,word ptr cs:[crter_flg-256]                                 ; Point BX to Critical Error flag
  191.   cmp al,byte ptr es:[bx]                                            ; See if Critical Error flag is set
  192.   pop es                                                             ; Restore ES
  193.   pop bx                                                             ; Restore BX
  194.   pop ax                                                             ; Restore AX
  195.   jae int1c_isr_reset                                                ; If Critical Error is set reset elapsed and return
  196.   push ax                                                            ; Preserve AX
  197.   mov ax,1680h                                                       ; Int 2F, function 1680h, Release current time slice
  198.   pushf                                                              ; Push flags onto stack
  199.   call cs:oldint2f-256                                               ; Call multiplex interrupt
  200.   pop ax                                                             ; Restore AX
  201. int1c_isr_reset:
  202.   mov word ptr cs:[elapsed-256],0000h                                ; Reset elapsed to zero
  203.   jmp int1c_isr_end                                                  ; Jump to IRET
  204. int1c_isr_inc:            
  205.   inc word ptr cs:[elapsed-256]                                      ; Increment elapsed tick counter
  206. int1c_isr_end:
  207.   iret                                                               ; Interrupt return from procedure
  208.  
  209. endmark:                                                             ; Used for TSR paragraph calc
  210.  
  211. install:
  212.   mov bx,cs                                                          ; Initialize DS & ES to equal CS
  213.   mov ds,bx
  214.   mov es,bx
  215.  
  216.   mov ax,offset giveup_end                                           ; Store size of full program into AX  
  217.   mov cl,04h                                                         ; Divide AX by 4 to get paragraphs
  218.   shr ax,cl                                                          ; Paragraphs now in AX
  219.   inc ax                                                             ; Add one for good measure
  220.   mov bx,ax                                                          ; Paragraph size goes in BX
  221.   mov ax,4A00h                                                       ; DOS func 4A, Resize memory block
  222.   int 21h                                                            ; Call DOS
  223.  
  224.   mov ah,49h                                                         ; DOS function 49h, release memory block
  225.   mov bx,2Ch                                                         ; Offset in PSP of program environment segment address
  226.   mov cx,word ptr es:[bx]                                            ; Retrieve that segment address into CX
  227.   mov es,cx                                                          ; And load into ES
  228.   int 21h                                                            ; Call DOS
  229.   mov bx,cs                                                          ; Reset ES
  230.   mov es,bx
  231.  
  232.   mov ah,09h                                                         ; DOS Print message function
  233.   mov dx,offset msg0                                                 ; Print ownership message
  234.   int 21h                                                            ; Call DOS
  235.  
  236. install_chek:                                                        ; Check if already installed
  237.   mov ax,0BADDh                                                      ; GIVE-UP multiplex ID is BADDh
  238.   int 2Fh                                                            ; Call multiplex interrupt
  239.   cmp ax,0FADEh                                                      ; AX=FADEh GIVE-UP is installed
  240.   jne cmd_line                                                       ; If not installed the continue
  241.   jmp already_installed                                              ; Do nothing and exit
  242.  
  243. cmd_line:                                                            ; Find trigger interval on command line
  244.   cld                                                                ; Clear direction flag (Count upward)  
  245.   mov di,0080h                                                       ; Offset of command tail in PSP
  246.   mov cx,007Fh                                                       ; Length of command tail in PSP
  247.   mov al,0Dh                                                         ; Character to search for (CR first to prevent screwups w/OS2)
  248.   repne scasb                                                        ; Scan for CR
  249.   mov cx,di                                                          ; Move offset of CR into CX
  250.   sub cx,0080h                                                       ; Subtract 80h, this is new max scan length
  251.   mov di,0080h                                                       ; Offset of command tail in PSP
  252.   mov al,'/'                                                         ; Character to search for
  253.   repne scasb                                                        ; Scan for /
  254.   cmp cl,00h                                                         ; If CL = 0 then / was not found
  255.   je loader                                                          ; Load with default of every 4 ticks
  256.   mov word ptr cs:[whenmask],0000h                                   ; Zero the trigger interval
  257.   mov al,byte ptr es:[di]                                            ; Move the byte into AL
  258.   sub al,30h                                                         ; Convert from ASCII into a number
  259.   mov bl,10                                                          ; Store 10 into BL
  260.   xor ah,ah                                                          ; Zero AH
  261.   mul bl                                                             ; Multiply by 10
  262.   add word ptr cs:[whenmask],ax                                      ; Add it to the trigger interval
  263.   inc di                                                             ; Increment DI to next character
  264.   mov al,byte ptr es:[di]                                            ; Move the byte into AL
  265.   sub al,30h                                                         ; Convert from ASCII into a number
  266.   xor ah,ah                                                          ; Zero AH
  267.   add word ptr cs:[whenmask],ax                                      ; Add it to the trigger interval
  268.  
  269. loader:                                                              ; Install the ISRs and their data
  270.   mov ax,5800h                                                       ; DOS function 58, sub func 00, Get allocation strategy  
  271.   int 21h                                                            ; Call DOS
  272.   mov word ptr cs:[strat],ax                                         ; Store the current allocation strategy
  273.  
  274.   mov ax,5801h                                                       ; DOS function 58, sub func 01, Set allocation strategy
  275.   mov bx,0002h                                                       ; To a last fit strategy
  276.   int 21h                                                            ; Call DOS
  277.  
  278.   mov bx,offset start                                                ; Get the offset of the start label
  279.   mov ax,offset endmark                                              ; Get offset of the endmark label
  280.   sub ax,bx                                                          ; Find number of bytes between start and endmark
  281.   mov cl,04h                                                         ; Divide AX by 16 to get paragraphs
  282.   shr ax,cl                                                          ; Paragraphs now in AX
  283.   inc ax                                                             ; Just in case
  284.  
  285.   mov bx,ax                                                          ; Store number of paragraphs into BX
  286.   mov ax,4800h                                                       ; DOS func. 48h, allocate memory
  287.   int 21h                                                            ; Call DOS
  288.   mov word ptr cs:[iseg],ax                                          ; Store newly allocated segment address
  289.  
  290.   mov ax,5801h                                                       ; DOS function 58, sub func 01, Set allocation strategy
  291.   mov bx,word ptr cs:[strat]                                         ; Restore the current strategy                                        
  292.   int 21h                                                            ; Call DOS
  293.  
  294.   push es                                                            ; Preserve ES
  295.   mov ax,word ptr cs:[iseg]                                          ; Load the ISR segment
  296.   dec ax                                                             ; Decrementing it points it to the correct MCB
  297.   mov es,ax                                                          ; Point ES to it
  298.   mov bx,0001h                                                       ; Offset in MCB of owner PID
  299.   mov word ptr es:[bx],0008h                                         ; DOS' PID is always 8
  300.   pop es                                                             ; Restore ES
  301.  
  302.   mov ax,offset int1c_isr                                            ; Calculate the Int 1Ch isr offset
  303.   sub ax,256                                                         ; By subtracting the PSP, the new offset is left
  304.   mov word ptr cs:[off1c],ax                                         ; Store it out
  305.  
  306.   mov ax,offset int28_isr                                            ; Calculate the Int 28h isr offset
  307.   sub ax,256                                                         ; By subtracting the PSP, the new offset is left
  308.   mov word ptr cs:[off28],ax                                         ; Store it out
  309.  
  310.   mov ax,offset int2f_isr                                            ; Calculate the Int 2fh isr offset
  311.   sub ax,256                                                         ; By subtracting the PSP, the new offset is left
  312.   mov word ptr cs:[off2f],ax                                         ; Store it out
  313.  
  314.   mov ax,3400h                                                       ; Int 21h, func 3400h, Get In-DOS flag address
  315.   int 21h                                                            ; Call DOS
  316.   mov word ptr [indos_flg],bx                                        ; Offset of In-DOS flag
  317.   mov word ptr [indos_flg+2],es                                      ; Segment of In-DOS flag
  318.  
  319.   push ds                                                            ; Preserve DS 
  320.   push si                                                            ; Preserve SI
  321.   mov ax,5D06h                                                       ; Int 21h, func 5D06h, Get DOS Swappable Data Area
  322.   int 21h                                                            ; Call DOS
  323.   mov word ptr [crter_flg],si                                        ; Offset of Critical Error Flag
  324.   mov word ptr [crter_flg+2],ds                                      ; Segment of Critical Error Flag
  325.   pop si                                                             ; Restore SI
  326.   pop ds                                                             ; Restore DS
  327.  
  328.   mov ax,351Ch                                                       ; Save the current INT 1Ch handler address
  329.   int 21h                                                            ; Call DOS
  330.   mov word ptr [oldint1c],bx                                         ; Offset of INT 1Ch ISR
  331.   mov word ptr [oldint1c+2],es                                       ; Segment of INT 1Ch ISR
  332.  
  333.   mov ax,3528h                                                       ; Save the current INT 28h handler address
  334.   int 21h                                                            ; Call DOS
  335.   mov word ptr [oldint28],bx                                         ; Offset of INT 28h ISR
  336.   mov word ptr [oldint28+2],es                                       ; Segment of INT 1Ch ISR
  337.  
  338.   mov ax,352fh                                                       ; Save the current INT 2fh handler address
  339.   int 21h                                                            ; Call DOS
  340.   mov word ptr [oldint2f],bx                                         ; Offset of INT 2fh ISR
  341.   mov word ptr [oldint2f+2],es                                       ; Segment of INT 2fh ISR
  342.  
  343.   push es                                                            ; Preserve ES
  344.   push ds                                                            ; Preserve DS
  345.   push di                                                            ; Preserve DI
  346.   push si                                                            ; Preserve SI
  347.   pushf                                                              ; Preserve the flags
  348.   mov bx,word ptr cs:[iseg]                                          ; Point ES to the new ISR segment
  349.   mov es,bx
  350.   mov si,offset start                                                ; DS:SI points to source
  351.   mov di,0000h                                                       ; ES:DI points to destination
  352.   mov bx,offset start                                                ; BX holds start
  353.   mov ax,offset endmark                                              ; AX holds endmark
  354.   sub ax,bx                                                          ; AX holds number of bytes to copy
  355.   mov cx,ax                                                          ; Now CX holds it
  356.   cld                                                                ; Copy goes from lo to hi
  357.   rep movsb                                                          ; Copy all of the ISR code and data to its new home
  358.   popf                                                               ; Restore the flags
  359.   pop si                                                             ; Restore SI
  360.   pop di                                                             ; Restore DI
  361.   pop ds                                                             ; Restore DS
  362.   pop es                                                             ; Restore ES
  363.  
  364.   push ds                                                            ; Preserve DS
  365.   mov bx,word ptr cs:[iseg]                                          ; Point DS to new ISR segment
  366.   mov ds,bx
  367.  
  368.   mov ax,251Ch                                                       ; Insert my own Int 1Ch handler in ISR chain
  369.   mov dx,word ptr cs:[off1c]                                         ; DS:DX points to ISR
  370.   int 21h                                                            ; Call DOS
  371.  
  372.   mov ax,2528h                                                       ; Insert my own Int 1Ch handler in ISR chain
  373.   mov dx,word ptr cs:[off28]                                         ; DS:DX points to ISR
  374.   int 21h                                                            ; Call DOS
  375.  
  376.   mov ax,252fh                                                       ; Insert my own Int 2Fh handler in ISR chain
  377.   mov dx,word ptr cs:[off2f]                                         ; DS:DX points to ISR
  378.   int 21h                                                            ; Call DOS
  379.   pop ds                                                             ; Restore DS
  380.   mov ax,4C00h                                                       ; Terminate with errorlevel=0
  381.   jmp exit                                                           ; And exit
  382.  
  383. already_installed:                                                 
  384.   mov ah,09h                                                         ; Print already installed message
  385.   mov dx,offset msg4
  386.   int 21h                                                            ; Call DOS
  387.   mov ax,4CFFh                                                       ; If no revectoring then errorlevel=255
  388.  
  389. exit:                                                                ; Terminate normally
  390.   int 21h                                                            ; Call DOS
  391.  
  392.  
  393. ; Data at end of code so it isn't kept when program goes TSR
  394.   strat dw  0000h                                                    ; DOS allocation strategy
  395.   iseg  dw  0000h                                                    ; Segment allocated for ISRs and data
  396.  
  397.   off1c dw  0000h                                                    ; Offset of int 1Ch isr
  398.   off28 dw  0000h                                                    ; Offset of int 28h isr
  399.   off2f dw  0000h                                                    ; Offset of int 2Fh isr
  400.  
  401.   msg0  db  13,10,'GIVE-UP TSR for OS/2, WinNT, Win95 & WFW',13,10
  402.   msg1  db  'By: Paul Trout, Bionic Fish Software Foundry',13,10
  403.   msg2  db  '23 Mar. 1996 -- V2R1',13,10,13,10,'$'
  404.   msg4  db  'GIVE-UP already installed, Not going TSR',13,10,'$'
  405.  
  406. giveup_end:                                                          ; True end of program marker                                                           
  407. _CODE ENDS
  408. END start
  409.  
  410.